/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
 * Copyright (C) 2016-2018, LomboTech Co.Ltd.
 * Author: lomboswer <lomboswer@lombotech.com>
 *
 * i2c.h - I2C host driver code for LomboTech
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 */
#ifndef ___I2C_H___
#define ___I2C_H___

#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_clock.h>
#include <linux/clk.h>
#include <linux/pinctrl/consumer.h>
#include <linux/random.h>
#include <mach/csp.h>
#include <asm/cacheflush.h>
#include <linux/dma-mapping.h>
/* #define ENABLE_TRACE */
#include <mach/debug.h>
#include <linux/of_reserved_mem.h>

#undef MOD_NAME
#define MOD_NAME	"I2C"
#define I2C_FUNC_CQI		0x00000100 /* CQI FUNC */

#define I2CCQI_16BIT_REG	0x0020
#define I2CCQI_16BIT_VAL	0x0040
#define I2CCQI_USE		0x0080

#if defined(CONFIG_ARCH_LOMBO_N9V1_FPGA) || \
	defined(CONFIG_ARCH_LOMBO_N7V3_FPGA) || \
	defined(CONFIG_ARCH_LOMBO_N7V5_FPGA) || \
	defined(CONFIG_ARCH_LOMBO_N5V1_FPGA) || \
	defined(CONFIG_ARCH_LOMBO_N9V3_FPGA)
#define CONFIG_ARCH_LOMBO_FPGA
#endif

#if defined(CONFIG_ARCH_LOMBO_N9V1) || defined(CONFIG_ARCH_LOMBO_N7V3)
#define AUTO_MODE
#include "csp/n9v1/i2c_csp.h"
#include "csp/n9v1/i2c_const.h"
#elif defined(CONFIG_ARCH_LOMBO_N7V5)
#define AUTO_MODE
#include "csp/n7v5/i2c_csp.h"
#include "csp/n7v5/i2c_const.h"
#elif defined(CONFIG_ARCH_LOMBO_N5V1)
#define AUTO_MODE
#include "csp/n5v1/i2c_csp.h"
#include "csp/n5v1/i2c_const.h"
#elif defined(CONFIG_ARCH_LOMBO_N9V3)
//#define AUTO_MODE
#include "csp/n9v3/i2c_csp.h"
#include "csp/n9v3/i2c_const.h"
#else
#include "csp/n7v1/i2c_csp.h"
#include "csp/n7v1/i2c_const.h"
#endif

#define I2C_MAX_CLK_PARENTS_CNT		3
#define I2C_IDLE_TIMEOUT		5000
#define I2C_HS_MASTERCODE_FREQ		400000

#define I2C_GATE			"i2c_gate"
#define I2C_REST			"i2c_reset"
#define I2C_MODULE_CLK			"i2c_module_clk"
#define I2C_CLK_PARENT0			"i2c_clk_parent0"
#define I2C_CLK_PARENT1			"i2c_clk_parent1"
#define I2C_MAXI_GATE			"i2c_maxi_gate"

#define I2C_IC_CLKRATE0			(24000000)
#define I2C_IC_CLKRATE1			(50000000)

#define lombo_i2c_chk_abrt(abrtsrc, mask)	\
	((abrtsrc & mask) == mask)

#ifdef msg
#undef msg
#endif

#if defined(CONFIG_ARCH_LOMBO_N7V3) || \
	defined(CONFIG_ARCH_LOMBO_N7V5)	|| \
	defined(CONFIG_ARCH_LOMBO_N5V1) || \
	defined(CONFIG_ARCH_LOMBO_N9V3)
/* cqi command queue parameter struct begin-----*/
struct lombo_i2c_cqi_qpara {
	u32			cmd_list_cnt;
	void			*msgs;
	u32			dev_addr;
	u32			msg_num;
	u32			reg_bit;
	u32			data_bit;
	u32			data_byte;

	u32			config_cmd_num;
	u32			list_config_num;
	u32			list_num;
	u32			tail_list_config_num;
	u32			list_cmd_num;
	u32			tail_list_cmd_num;
};
/* cqi command queue parameter struct end-----*/

/*cqi data struct begin-------------------------*/
struct lombo_i2c_cqi {
	u64			**list_queue;
	u64			*buf;
	dma_addr_t		dma_add;
	/*  */
	struct lombo_i2c_cqi_qpara qpara;

};
/*cqi data struct end-------------------------*/
#endif

struct lombo_i2c {
	u32			baudrate;	/* the baudrate of the bus */

	u32			ic_clkrate;	/* frequence of ic_clk */
	u32			actual_rate;	/* actual baudrate of the bus */
	u32			speed_mode;

	u32			fs_spk_len;	/* FS mode max spike length */
	u32			hs_spk_len;	/* HS mode max spike length */
	/* to adjust the high period of SCL */
	u32			h_adj_cnt;
	/* to adjust the low period of SCL */
	u32			l_adj_cnt;
	/* start address of the msgs sequence */
	struct i2c_msg		*msgs;
	/* number of the msgs sequence */
	u32			msg_num;
	/* the current msg to send cmd */
	u32			msg_send;
	/* the msgs before it have already been read */
	u32			msg_read;
	/* the current byte of the current msg to send cmd */
	u32			msg_byte_send;
	/* he current byte of the current msg to be read */
	u32			msg_byte_read;
	/* count of the bytes need to read */
	u32			msg_pd_rd_cnt;

	u32			msg_rw_byte;
	u32			msg_pd_rw_cnt;
	int			msg_err;	/* Error number */
	/* for waiting transfer complete */
	wait_queue_head_t	wait;
	/* mark if the bus is suspended */
	unsigned int		suspended:1;

	unsigned int		irq;		/* irq number of the I2CC */

	u32			reg_base;
	void __iomem		*base;		/* base address of the I2CC */
	struct clk		*clk_i2c;	/* I2CC module clock */
	struct clk		*clk_gate;	/* I2CC apb clock gate */
	struct clk		*clk_reset;	/* I2CC apb clock reset */
	struct clk		*clk_parent0;	/* I2CC module clock parent0 */
	struct clk		*clk_parent1;	/* I2CC module clock parent1 */
	struct clk		*clk_maxi_gate;	/* I2CCQI MEMORY AXI bus clk */

	spinlock_t		lock;

	u32			imask;
	u32			int_status;
	u32			abrtsrc;

	/* driver module device structure */
	struct device		*dev;
	/* common i2c adapter structure */
	struct i2c_adapter	adap;

	struct pinctrl          *pctrl;		/* pinctrl of the I2CC */
#if defined(CONFIG_ARCH_LOMBO_N7V3) || \
	defined(CONFIG_ARCH_LOMBO_N7V5) || \
	defined(CONFIG_ARCH_LOMBO_N5V1) || \
	defined(CONFIG_ARCH_LOMBO_N9V3)
	struct lombo_i2c_cqi	cqi;
#endif
};

irqreturn_t lombo_cqi_irq(struct lombo_i2c *i2c, int irqno, void *dev_id);

void lombo_cqi_node(struct platform_device *pdev);

int lombo_cqi_xfer(struct i2c_adapter *adap, u32 addr,
			void *msgs, u32 sum,
			u32 reg_bit, u32 data_bit);

void lombo_cqi_req_queue_buf(struct lombo_i2c *i2c);
void lombo_cqi_unreq_queue_buf(struct lombo_i2c *i2c);

#endif
